import { CompletionContext, CompletionSource } from "@codemirror/autocomplete";
import { syntaxTree } from "@codemirror/language";
import { EditorState } from "@codemirror/state";
import { SyntaxNode } from "@lezer/common";
import { ancestorOfNodeWithType } from "./ancestors";
import { BaseMethods } from "rdjs-wheel";

export const ifInType = (
  type: string,
  source: CompletionSource
): CompletionSource => {
  let completionSource: CompletionSource = (context: CompletionContext) => {
    const tree = syntaxTree(context.state);
    let node: SyntaxNode | null = tree.resolveInner(context.pos, -1);
    while (node) {
      if (node.type.is(type)) {
        return source(context);
      }
      node = node.parent;
    }
    return null;
  };
  return completionSource;
};

function isInEmptyArgumentNodeOfType(state: EditorState, types: string[]) {
  const main = state.selection.main;
  if (!main.empty) {
    return false;
  }

  const pos = main.anchor;
  const tree = syntaxTree(state);

  if (tree.length < pos) {
    return false;
  }

  const nodeLeft = tree.resolveInner(pos, -1);
  if (!nodeLeft.type.is("OpenBrace")) {
    return false;
  }

  const nodeRight = tree.resolveInner(pos, 1);
  if (!nodeRight.type.is("CloseBrace")) {
    return false;
  }

  const ancestor = ancestorOfNodeWithType(nodeLeft, ...types);
  if (!ancestor) {
    return false;
  }

  return ancestor.from === nodeLeft.from && ancestor.to === nodeRight.to;
}

export function isInEmptyArgumentNodeForAutocomplete(state: EditorState) {
  return isInEmptyArgumentNodeOfType(state, [
    "EnvNameGroup",
    "BibliographyStyleArgument",
    "BibliographyArgument",
    "BibKeyArgument",
    "DocumentClassArgument",
    "FilePathArgument",
    "RefArgument",
    "PackageArgument",
  ]);
}

export function isInEmptyCiteArgumentNode(state: EditorState) {
  return isInEmptyArgumentNodeOfType(state, ["BibKeyArgument"]);
}
